home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / util / deemu.1 next >
Text File  |  1988-10-25  |  39KB  |  1,459 lines

  1. Path: xanth!nic.MR.NET!tank!mimsy!dftsrv!ames!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i024:  deemu - user modifiable executable embedded data (REPOST)
  5. Message-ID: <9841@swan.ulowell.edu>
  6. Date: 25 Oct 88 04:30:05 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 1447
  9. Approved: page@swan.ulowell.edu
  10. Supersedes: <9835@swan.ulowell.edu>
  11.  
  12. Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
  13. Posting-number: Volume 2, Issue 24
  14. Archive-name: util/deemu.1
  15.  
  16. [ignore the first deemu source posting if it's at your site, it had
  17. two docs missing.  ..Bob]
  18.  
  19. DEEMU allows end users to modify various parameters of a program by
  20. directly modifying the executable in question through standard
  21. programs.
  22.  
  23. # This is a shell archive.  Remove anything before this line
  24. # then unpack it by saving it in a file and typing "sh file"
  25. # (Files unpacked will be owned by you and have default permissions).
  26. # This archive contains the following files:
  27. #    Makefile
  28. #    clock.c
  29. #    clock.doc
  30. #    config.c
  31. #    config.doc
  32. #    deemu.doc
  33. #    script.txt
  34. #
  35. if `test ! -s Makefile`
  36. then
  37. echo "writing Makefile"
  38. cat > Makefile << '\Rogue\Monster\'
  39.  
  40. #   Makefile for config and clock    AZTEC C, +L (32 bit ints)
  41. #
  42. #   NOTE:  I rely on a precompiled include file.  If you do not have such
  43. #   a file, it should not be too hard to add the appopriate #include's...
  44. #   my precompiled include files (precompiled under +L and +H) has only
  45. #   the sub-directory Amiga includes  (*/*.h).
  46.  
  47. SYMS=    include:symbols.m
  48. SYMC=    include:local/makesymbols.c
  49. CFLAGS= +L +I$(SYMS)
  50.  
  51.  
  52. all:    $(SYMS) config clock
  53.  
  54. config:     config.o
  55.     ln +Q config.o -lc32
  56.  
  57. clock:        clock.o
  58.     ln +Q clock.o -lc32
  59.  
  60. $(SYMS):    $(SYMC)
  61.     make -f include:local/Makefile
  62.  
  63.  
  64. \Rogue\Monster\
  65. else
  66.   echo "will not over write Makefile"
  67. fi
  68. if [ `wc -c Makefile | awk '{printf $1}'` -ne 587 ]
  69. then
  70. echo `wc -c Makefile | awk '{print "Got " $1 ", Expected " 587}'`
  71. fi
  72. if `test ! -s clock.c`
  73. then
  74. echo "writing clock.c"
  75. cat > clock.c << '\Rogue\Monster\'
  76.  
  77. /*
  78.  *  CLOCK.C    simple clock program
  79.  */
  80.  
  81. #include <local/typedefs.h>
  82.  
  83. short Params[] = {
  84.     'ST','RT', 0, 0,
  85.     'NW','  ', 0, 8, -1, 10, 40, 20,
  86.     'TE','XT', 0,16, 'HI','\0T','ES','T.', 0, 0, 0, 0,
  87.     'EN','D ', 0, 0
  88. };
  89.  
  90. #define WPOSX    8
  91. #define WPOSY    9
  92. #define WWIDTH    10
  93. #define WHEIGHT 11
  94.  
  95. APTR IntuitionBase;
  96. APTR GfxBase;
  97.  
  98. NW Nw = {
  99.     0, 0, 0, 0, 0, 0,
  100.     CLOSEWINDOW|REFRESHWINDOW|ACTIVEWINDOW|INACTIVEWINDOW,
  101.     SIMPLE_REFRESH|WINDOWCLOSE|BACKDROP|RMBTRAP,
  102.     NULL, NULL, (ubyte *)"", NULL, NULL, 4, 4, -1, -1, WBENCHSCREEN
  103. };
  104.  
  105. short Sin[60+15] = {
  106.       0,  27,  53,  79, 104, 128, 150, 171, 190, 207, 222, 234, 243, 250, 255,
  107.     256, 255, 250, 243, 234, 222, 207, 190, 171, 150, 128, 104,  79,  53,  27,
  108.       0, -27, -53, -79,-104,-128,-150,-171,-190,-207,-222,-234,-243,-250,-255,
  109.    -256,-255,-250,-243,-234,-222,-207,-190,-171,-150,-128,-104, -79, -53, -27,
  110.       0,  27,  53,  79, 104, 128, 150, 171, 190, 207, 222, 234, 243, 250, 255
  111. };
  112.  
  113. #define Cos (Sin+15)
  114.  
  115. _main(ac, av)
  116. char *av[];
  117. {
  118.     IOT  Iot;        /*    timer request,    1 second internals  */
  119.     SCR  Scr;
  120.     WIN  *Win;
  121.     PORT TPort;     /*    port for timer request            */
  122.     long TMask;
  123.     long WMask;
  124.     long error = 20;
  125.     char notdone = 1;
  126.  
  127.     bzero(&Iot, sizeof(Iot));
  128.     bzero(&TPort, sizeof(TPort));
  129.  
  130.     if (!(IntuitionBase = OpenLibrary("intuition.library", 0)))
  131.     goto dieilib;
  132.     if (!(GfxBase = OpenLibrary("graphics.library", 0)))
  133.     goto dieglib;
  134.     if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0))
  135.     goto diedev;
  136.     if (!GetScreenData(&Scr, sizeof(Scr), WBENCHSCREEN, NULL))
  137.     goto diewin;
  138.  
  139.     Nw.Width  = Params[WWIDTH];
  140.     Nw.Height = Params[WHEIGHT];
  141.     Nw.LeftEdge = Params[WPOSX];
  142.     Nw.TopEdge    = Params[WPOSY];
  143.     if (Nw.Width <= 0)
  144.     Nw.Width += Scr.Width;
  145.     if (Nw.Height <= 0)
  146.     Nw.Height += Scr.Height;
  147.     if (Nw.LeftEdge < 0)
  148.     Nw.LeftEdge += Scr.Width - Nw.Width;
  149.     if (Nw.TopEdge < 0)
  150.     Nw.TopEdge  += Scr.Height- Nw.Height;
  151.     if (Nw.LeftEdge < 0 || Nw.TopEdge < 0 || Nw.LeftEdge + Nw.Width > Scr.Width || Nw.TopEdge + Nw.Height > Scr.Height) {
  152.     Nw.LeftEdge = Nw.TopEdge = 0;
  153.     Nw.Width = 64;
  154.     Nw.Height= 32;
  155.     }
  156.  
  157.     if (!(Win = OpenWindow(&Nw)))
  158.     goto diewin;
  159.  
  160.     ShowTitle(Win->WScreen, 0);
  161.  
  162.     TPort.mp_Node.ln_Type = NT_MSGPORT;
  163.     TPort.mp_SigTask = FindTask(NULL);
  164.     TPort.mp_SigBit = AllocSignal(-1);
  165.     TPort.mp_Flags  = PA_SIGNAL;
  166.     NewList(&TPort.mp_MsgList);
  167.  
  168.     Iot.tr_node.io_Message.mn_ReplyPort = &TPort;
  169.     Iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  170.     Iot.tr_node.io_Command = TR_ADDREQUEST;
  171.     Iot.tr_time.tv_secs = 1;
  172.     Iot.tr_time.tv_micro= 0;
  173.     SendIO(&Iot);
  174.  
  175.     TMask = 1 << TPort.mp_SigBit;
  176.     WMask = 1 << Win->UserPort->mp_SigBit;
  177.  
  178.     error = 0;
  179.     while (notdone) {
  180.     register long mask = Wait(TMask|WMask);
  181.     if (mask & TMask) {
  182.         register short secs;
  183.         WaitIO(&Iot);
  184.         secs = UpdateWindow(Win);
  185.         Iot.tr_time.tv_secs = 65 - secs;
  186.         Iot.tr_time.tv_micro= 0;
  187.         Iot.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  188.         SendIO(&Iot);
  189.     }
  190.     if (mask & WMask) {
  191.         register IMESS *im;
  192.         while (im = GetMsg(Win->UserPort)) {
  193.         switch(im->Class) {
  194.         case CLOSEWINDOW:
  195.             notdone = 0;
  196.             break;
  197.         case REFRESHWINDOW:
  198.             BeginRefresh(Win);
  199.             EndRefresh(Win);
  200.         case ACTIVEWINDOW:
  201.         case INACTIVEWINDOW:
  202.             UpdateWindow(Win);
  203.             break;
  204.         }
  205.         ReplyMsg(im);
  206.         }
  207.     }
  208.     }
  209.     AbortIO(&Iot);
  210.     WaitIO(&Iot);
  211.     FreeSignal(TPort.mp_SigBit);
  212.  
  213.     CloseWindow(Win);
  214. diewin:
  215.     CloseDevice(&Iot);
  216. diedev:
  217.     CloseLibrary(GfxBase);
  218. dieglib:
  219.     CloseLibrary(IntuitionBase);
  220. dieilib:
  221.     _exit(error);
  222. }
  223.  
  224. /*
  225.  *  Update the window
  226.  *
  227.  *  (1) RectFill
  228.  *  (2) minute and hour hands
  229.  */
  230.  
  231. UpdateWindow(win)
  232. register WIN *win;
  233. {
  234.     register RP *rp = win->RPort;
  235.     DATESTAMP DS;
  236.     short minutes;
  237.     short hours;
  238.     short radiusx, radiusy;
  239.     short centerx, centery;
  240.  
  241.     DateStamp(&DS);
  242.     minutes = DS.ds_Minute % 60;
  243.     hours   = (DS.ds_Minute / 12) % 60;     /*  0 to 59 (partial hours indicator)   */
  244.     radiusx = (win->Width - 2) >> 1;
  245.     radiusy = (win->Height- 2) >> 1;
  246.     centerx = 1 + radiusx;
  247.     centery = 1 + radiusy;
  248.     SetAPen(rp, 0);
  249.     RectFill(rp, 0, 0, win->Width - 1, win->Height - 1);
  250.     SetAPen(rp, 1);
  251.     {
  252.     register short i;
  253.     for (i = 0; i < 60; i += 5) {
  254.         Move(rp, centerx + ((radiusx * Sin[i]) >> 8), centery + ((radiusy * -Cos[i]) >> 8));
  255.         Draw(rp, centerx + ((radiusx * Sin[i]) >> 8), centery + ((radiusy * -Cos[i]) >> 8));
  256.     }
  257.     }
  258.     radiusx -= 2;
  259.     radiusy -= 2;
  260.  
  261.     SetAPen(rp, 3);                 /*  minutes */
  262.     Move(rp, centerx, centery);
  263.     Draw(rp, centerx + ((radiusx * Sin[minutes]) >> 8), centery + ((radiusy * -Cos[minutes]) >> 8));
  264.     SetAPen(rp, 2);                 /*  hours   */
  265.     Move(rp, centerx, centery);
  266.     Draw(rp, centerx + ((radiusx * Sin[hours]) / 384), centery + ((radiusy * -Cos[hours]) / 384));
  267.     return(DS.ds_Tick / 50 % 60);  /*  seconds */
  268. }
  269.  
  270. #asm
  271.  
  272.         ; bzero(buf, bytes)
  273.         ;        4sp   8sp
  274.         ;
  275.         ;    SIMPLE STUPID BZERO .. I don't even use DBF (don't want to
  276.         ;                have to think at this time of night)
  277.  
  278. _bzero:
  279.         moveq.l #0,D1
  280.         move.l  4(sp),A0
  281.         move.l  8(sp),D0
  282.         beq     bze
  283. bz1        move.b  D1,(A0)+
  284.         subq.l  #1,D0
  285.         bne     bz1
  286. bze        rts
  287.  
  288.  
  289. #endasm
  290.  
  291. \Rogue\Monster\
  292. else
  293.   echo "will not over write clock.c"
  294. fi
  295. if [ `wc -c clock.c | awk '{printf $1}'` -ne 5293 ]
  296. then
  297. echo `wc -c clock.c | awk '{print "Got " $1 ", Expected " 5293}'`
  298. fi
  299. if `test ! -s clock.doc`
  300. then
  301. echo "writing clock.doc"
  302. cat > clock.doc << '\Rogue\Monster\'
  303.  
  304.     This clock has no options.    Use the CONFIG program to configure the
  305.     executable:
  306.  
  307.     config clock
  308.  
  309.     then run it
  310.  
  311. \Rogue\Monster\
  312. else
  313.   echo "will not over write clock.doc"
  314. fi
  315. if [ `wc -c clock.doc | awk '{printf $1}'` -ne 124 ]
  316. then
  317. echo `wc -c clock.doc | awk '{print "Got " $1 ", Expected " 124}'`
  318. fi
  319. if `test ! -s config.c`
  320. then
  321. echo "writing config.c"
  322. cat > config.c << '\Rogue\Monster\'
  323.  
  324. /*
  325.  *  CONFIG.C
  326.  *
  327.  *  (C)Copyright 1988, Matthew Dillon, All Rights Reserved.
  328.  *  Permission is granted to distribute for non-profit only.
  329.  *
  330.  *  config file1 file2 file3.... filen
  331.  *
  332.  *  Configure one or more executables.    The executables must conform to
  333.  *  the Static User Modifiable Data Standard        (SUMDS)
  334.  *
  335.  *  This program configures the static parameters of C programs which
  336.  *  contain the appropriate structures.  Unknown parameters may be
  337.  *  configured in raw hex if you know the format.
  338.  */
  339.  
  340. #include <stdio.h>
  341.  
  342. #define arysize(array)  (sizeof(array)/sizeof(array[0]))
  343.  
  344. extern void *malloc();
  345.  
  346. typedef unsigned char    ubyte;
  347. typedef unsigned short    uword;
  348. typedef unsigned long    ulong;
  349.  
  350. char Show;
  351. char XDebug;
  352.  
  353. main(ac, av)
  354. char *av[];
  355. {
  356.     register short i;
  357.     FILE *fi;
  358.     long pos, len;
  359.  
  360.     puts("CONFIG V1.00, Matthew Dillon.");
  361.     for (i = 1; i < ac; ++i) {
  362.     fi = fopen(av[i], "r+");
  363.     if (fi == NULL) {
  364.         printf("Could not open %s for reading\n", av[i]);
  365.         continue;
  366.     }
  367.     switch(FindData(fi, &pos, &len)) {
  368.     case -2:
  369.         printf("%s contains unknown hunk #%ld\n", av[i], pos);
  370.         break;
  371.     case -1:
  372.         printf("%s is not an executable\n", av[i]);
  373.         break;
  374.     case  0:
  375.         printf("could not find configuration header in %s\n", av[i]);
  376.         break;
  377.     case  1:
  378.         switch(Configure(fi, pos, len*4)) {
  379.         case -3:
  380.         printf("Unable to malloc %ld bytes\n", len);
  381.         break;
  382.         case -2:
  383.         puts("Error reading data block or badly formatted data");
  384.         break;
  385.         case -1:
  386.         puts("No 'END ' entry found in header");
  387.         break;
  388.         case 0:
  389.         puts("No modifications made to file");
  390.         break;
  391.         case 1:
  392.         puts("File updated");
  393.         break;
  394.         }
  395.         break;
  396.     }
  397.     fclose(fi);
  398.     }
  399. }
  400.  
  401. /*
  402.  *  Search through the beginning of all HUNK_DATA hunks for 'STRT', 0
  403.  *
  404.  *  symb:   object modules only, not defined here.
  405.  *    HUNK_OVERLAY cannot be handled yet.
  406.  */
  407.  
  408. #define HUNK_UNIT    999    /*  N, Nlws of name        */
  409. #define HUNK_NAME    1000    /*  N, Nlws of name        */
  410. #define HUNK_CODE    1001    /*  N, Nlws of code        */
  411. #define HUNK_DATA    1002    /*  N, Nlws of data        */
  412. #define HUNK_BSS    1003    /*  N    (Nlws of bss)       */
  413. #define HUNK_RELOC32    1004    /*  N, (N+1)lws, N ... 0    */
  414. #define HUNK_RELOC16    1005    /*  N, (N+1)lws, N ... 0    */
  415. #define HUNK_RELOC8    1006    /*  N, (N+1)lws, N ... 0    */
  416. #define HUNK_EXT    1007    /*  N, symb,symb... 0        */
  417. #define HUNK_SYMBOL    1008    /*  N, symb,symb... 0        */
  418. #define HUNK_DEBUG    1009    /*  N, Nlws of debug        */
  419. #define HUNK_END    1010    /*  -                */
  420. #define HUNK_HEADER    1011    /*  N, Nlwsname, N.. 0, tabsize, F, L, F-L+1 sizes  */
  421. #define HUNK_OVERLAY    1013    /*  tabsize, M+2,M+1 ... ovr data table         */
  422. #define HUNK_BREAK    1014    /*  -                */
  423.  
  424. FindData(fi, ppos, plen)
  425. FILE *fi;
  426. long *ppos;
  427. long *plen;
  428. {
  429.     long type;
  430.     long len;
  431.     long pos;
  432.     long ary[3];
  433.     static long buf[256];
  434.  
  435.     if (fread(&type, 4, 1, fi) != 1 || type != HUNK_HEADER)
  436.     return(-1);
  437.     for (;;) {
  438.     if (fread(&len, 4, 1, fi) != 1)
  439.         return(-1);
  440.     if (len == 0)
  441.         break;
  442.     fseek(fi, len*4, 1);
  443.     }
  444.     if (fread(ary, 4, 3, fi) != 3)
  445.     return(-1);
  446.     fseek(fi, 4*(ary[2] - ary[1] + 1), 1);
  447.  
  448.     while (fread(&type, 4, 1, fi) == 1) {
  449.     len = 0;
  450.     if (XDebug)
  451.         printf("type: %ld\n", type);
  452.     switch(type) {
  453.     case HUNK_CODE:
  454.         fread(&len, 4, 1, fi);
  455.         break;
  456.     case HUNK_DATA:
  457.         fread(&len, 4, 1, fi);      /*  # of longwords  */
  458.         pos = ftell(fi);
  459.         if (len >= 4) {
  460.         register short i;
  461.         register short j = (len > arysize(buf)) ? arysize(buf) : len;
  462.         register long *ptr;
  463.         fread(buf, j, 4, fi);
  464.         for (i = 0; i < j; ++i) {
  465.             ptr = buf + i;
  466.             if (ptr[0] == 'STRT' && ptr[1] == 0) {
  467.             *ppos = pos+i*4;
  468.             *plen = len - i;
  469.             fseek(fi, *ppos, 0);
  470.             return(1);
  471.             }
  472.             ptr = (long *)((short *)ptr + 1);
  473.             if (ptr[0] == 'STRT' && ptr[1] == 0) {
  474.             *ppos = pos+i*4+2;
  475.             *plen = len - i;
  476.             fseek(fi, *ppos, 0);
  477.             return(1);
  478.             }
  479.         }
  480.         }
  481.         fseek(fi, pos, 0);
  482.         break;
  483.     case HUNK_BSS:
  484.         fread(&len, 4, 1, fi);
  485.         len = 0;
  486.         break;
  487.     case HUNK_RELOC32:
  488.     case HUNK_RELOC16:
  489.     case HUNK_RELOC8:
  490.         for (;;) {
  491.         if (fread(&len, 4, 1, fi) != 1)
  492.             return(-1);
  493.         if (len == 0)
  494.             break;
  495.         ++len;
  496.         fseek(fi, len*4, 1);
  497.         }
  498.         break;
  499.     case HUNK_SYMBOL:
  500.         for (;;) {
  501.         if (fread(&len, 4, 1, fi) != 1)
  502.             return(-1);
  503.         if (len == 0)
  504.             break;
  505.         len = (len + 1) & 0x00FFFFFF;
  506.         if (len <= 32)                  /*  reading is faster */
  507.             fread(buf, len, 4, fi);
  508.         else                /*  very long name?   */
  509.             fseek(fi, len*4, 1);
  510.         }
  511.         break;
  512.     case HUNK_DEBUG:
  513.         if (fread(&len, 4, 1, fi) != 1)
  514.         return(-1);
  515.         break;
  516.     case HUNK_END:
  517.         break;
  518.     default:
  519.         *ppos = type;
  520.         return(-2);
  521.     }
  522.     fseek(fi, len*4, 1);
  523.     }
  524.     return(0);
  525. }
  526.  
  527. Configure(fi, pos, len)
  528. FILE *fi;
  529. long pos;
  530. long len;        /*  bytes   */
  531. {
  532.     register uword *buf = malloc(len+1);
  533.     register long i;
  534.     short j;
  535.     long modified = 0;
  536.     short numentries = 0;
  537.  
  538.     len >>= 1;        /*  Words   */
  539.  
  540.     if (buf == NULL)
  541.     return(-3);
  542.     fseek(fi, pos, 0);
  543.     if (fread(buf, len, 2, fi) != 2)
  544.     return(-2);
  545.     for (i = 4; i < len;) {
  546.     if (buf[i] == 'EN' && buf[i+1] == 'D ' && buf[i+2] == 0)
  547.         break;
  548.     ++numentries;
  549.     i += 4 + ((buf[i+3]+1)>>1);
  550.     }
  551.     if (i > len)
  552.     return(-2);
  553.     if (i == len)
  554.     return(-1);
  555.  
  556.     len = i;
  557.     printf("%ld entries found\n\n", numentries);
  558.  
  559.     for (i = 4; i < len;) {
  560.     register long data = (buf[i]<<16)|buf[i+1];
  561.     long dlen = buf[i+3];
  562.     uword *ptr = buf + i + 4;
  563.  
  564.     printf("----(%c%c%c%c,%2ld): ", data>>24, data>>16, data>>8, data, dlen);
  565.     switch(data) {
  566.     case 'NW  ':
  567.         puts("NEW WINDOW STRUCTURE");
  568.         modified += Edit_WINP(ptr, dlen);
  569.         break;
  570.     case 'TEXT':
  571.         puts("TEXT");
  572.         modified += Edit_TEXT(ptr, dlen);
  573.         break;
  574.     default:
  575.         puts("UNKNOWN STRUCTURE, HEX EDIT");
  576.         modified += Edit_Hex(ptr, dlen);
  577.         break;
  578.     }
  579.     i += 4 + ((dlen+1)>>1);
  580.     puts("");
  581.     }
  582.     {
  583.     long response = (modified) ? 0 : 'n';
  584.     char ibuf[64];
  585.  
  586.     while (response != 'y' && response != 'n') {
  587.         printf("Write data back to file (y/n): ");
  588.         fflush(stdout);
  589.         if (gets(ibuf) == NULL)
  590.         break;
  591.         response = ibuf[0] | 0x20;
  592.     }
  593.     if (response == 'y') {
  594.         fseek(fi, pos, 0);
  595.         fwrite(buf, len, 2, fi);
  596.         return(1);
  597.     } else {
  598.         return(0);
  599.     }
  600.     }
  601. }
  602.  
  603. Edit_WINP(buf, bytes)
  604. char *buf;
  605. short bytes;
  606. {
  607.     short i;
  608.     short modified = 0;
  609.  
  610.     for (i = 0; i < bytes;) {
  611.     switch(i) {
  612.     case 0:     /*    LeftEdge    */
  613.         modified += strscanvalue(buf+i, 2, "LeftEdge", "(Negative = Relative to Screen Right)");
  614.         i += 2;
  615.         break;
  616.     case 2:     /*    TopEdge     */
  617.         modified += strscanvalue(buf+i, 2, "TopEdge", "(Negative = Relative to Screen Bottom)");
  618.         i += 2;
  619.         break;
  620.     case 4:     /*    Width        */
  621.         modified += strscanvalue(buf+i, 2, "Width", "(0 = Full Width, < 0 = ScreenWidth - (-width)");
  622.         i += 2;
  623.         break;
  624.     case 6:     /*    Height    */
  625.         modified += strscanvalue(buf+i, 2, "Height", "(0 = Full Height, < 0 = ScreenHeight - (-height)");
  626.         i += 2;
  627.         break;
  628.     case 8:     /*    DetailPen   */
  629.         modified += strscanvalue(buf+i, 1, "DetailPen", NULL);
  630.         ++i;
  631.         break;
  632.     case 9:     /*    BlockPen    */
  633.         modified += strscanvalue(buf+i, 1, "BlockPen", NULL);
  634.         ++i;
  635.         break;
  636.     case 10:    /*    IDCMP        */
  637.         modified += strscanvalue(buf+i, 4, "IDCMP", NULL);
  638.         i += 4;
  639.         break;
  640.     case 14:    /*    Flags        */
  641.         modified += strscanvalue(buf+i, 4, "Flags", NULL);
  642.         i += 4;
  643.         break;
  644.     default:
  645.         i = bytes;
  646.         break;
  647.     }
  648.     }
  649.     return(modified);
  650. }
  651.  
  652. /*
  653.  *  Edit TEXT.    The buffer holds a 'type' string, \0, then space for a text
  654.  *  string.
  655.  */
  656.  
  657. Edit_TEXT(lb, len)
  658. char *lb;
  659. {
  660.     register short i, slen;
  661.     char buf[256];
  662.     char *prompt = lb;
  663.  
  664.     while (*lb) {
  665.     ++lb;
  666.     --len;
  667.     }
  668.     ++lb;
  669.     --len;
  670.     if (len <= 0) {
  671.     puts("TEXT ERROR: UNTERMINATED BUFFER");
  672.     return(0);
  673.     }
  674. loop:
  675.     printf("%-15s (%ld chars max) (%15s) :", prompt, len - 1, lb);
  676.     if (gets(buf) == NULL || buf[0] == 0)
  677.     strcpy(buf, lb);
  678.     if (strcmp(buf, lb) != 0) {
  679.     slen = strlen(buf);
  680.     if (slen > len - 1) {
  681.         printf("Maximum of %ld chars!", len - 1);
  682.         goto loop;
  683.     }
  684.     strcpy(lb, buf);
  685.     return(1);
  686.     }
  687.     return(0);
  688. }
  689.  
  690. Edit_Extended(i, size, lb)
  691. short i;
  692. char *lb;
  693. {
  694.     printf("    #%ld (Blind entry) ", i);
  695.     return(scanvalue(lb, size));
  696. }
  697.  
  698. Edit_Hex(lb, len)
  699. char *lb;
  700. long len;
  701. {
  702.     short modified = 0;
  703.     short i;
  704.  
  705.     puts("    (Unknown Type, blind data entry)");
  706.     for (i = 0; i < len; ++i) {
  707.     printf("    Entry %2ld/%2ld ", i, len-1);
  708.     modified += scanvalue(lb+i, 1);
  709.     }
  710.     return(modified);
  711. }
  712.  
  713. strscanvalue(lb, size, prompt, desc)
  714. char *lb;
  715. char *prompt;
  716. char *desc;
  717. {
  718.     if (desc)
  719.     printf(" note: %s\n", desc);
  720.     printf("%15s ", prompt);
  721.     return(scanvalue(lb, size));
  722. }
  723.  
  724. scanvalue(lb, size)
  725. ubyte *lb;
  726. {
  727.     register long val;
  728.     register char *str;
  729.     short neg;
  730.     char buf[128];
  731.  
  732. top:
  733.     switch(size) {
  734.     case 1:
  735.     val = *lb;
  736.     printf("(      $%02x     %3ld) :", val, (char)val);
  737.     break;
  738.     case 2:
  739.     val = *(uword *)lb;
  740.     printf("(    $%04x  %6ld) :", val, (short)val);
  741.     break;
  742.     case 4:
  743.     val = *(long *)lb;
  744.     printf("($%08lx %7ld) :", val, val);
  745.     break;
  746.     }
  747.     fflush(stdout);
  748.  
  749.     neg = 1;
  750.     if (gets(buf) && buf[0]) {
  751.     val = 0;
  752.     str = buf;
  753.     if (*str == '-') {
  754.         neg = -1;
  755.         ++str;
  756.     }
  757.                             /*    hex */
  758.     if (str[0] == '$' || (str[0] == '0' && (str[1]|0x20) == 'x')) {
  759.         if (*str++ != '$')
  760.         ++str;
  761.         for (; *str; ++str) {
  762.         *str |= 0x20;
  763.         if (*str >= '0' && *str <= '9') {
  764.             val = (val << 4) | (*str & 15);
  765.             continue;
  766.         }
  767.         if (*str >= 'a' && *str <= 'f') {
  768.             val = (val << 4) | (*str - 'a' + 10);
  769.             continue;
  770.         }
  771.         break;
  772.         }
  773.     } else
  774.     if (*str == '%') {                          /*  binary  */
  775.         for (++str; *str >= '0' && *str <= '1'; ++str)
  776.         val = (val << 1) | (*str & 1);
  777.     } else if (*str) {                          /*  decimal */
  778.         for (; *str >= '0' && *str <= '9'; ++str)
  779.         val = val * 10 + *str - '0';
  780.     }
  781.     if (*str) {
  782.         printf("Illegal char '%c', try again\n    ? ", *str);
  783.         goto top;
  784.     }
  785.     }
  786.     if (neg < 0)
  787.     val = -val;
  788.     switch(size) {
  789.     case 1:
  790.     if ((ubyte)val != *lb) {
  791.         *lb = val;
  792.         return(1);
  793.     }
  794.     break;
  795.     case 2:
  796.     if ((uword)val != *(uword *)lb) {
  797.         *(uword *)lb = val;
  798.         return(1);
  799.     }
  800.     break;
  801.     case 4:
  802.     if (val != *(long *)lb) {
  803.         *(long *)lb = val;
  804.         return(1);
  805.     }
  806.     break;
  807.     }
  808.     return(0);
  809. }
  810.  
  811.  
  812. \Rogue\Monster\
  813. else
  814.   echo "will not over write config.c"
  815. fi
  816. if [ `wc -c config.c | awk '{printf $1}'` -ne 10403 ]
  817. then
  818. echo `wc -c config.c | awk '{print "Got " $1 ", Expected " 10403}'`
  819. fi
  820. if `test ! -s config.doc`
  821. then
  822. echo "writing config.doc"
  823. cat > config.doc << '\Rogue\Monster\'
  824.  
  825.     PRELIMINARY PRELIMINARY PRELIMINARY PRELIMINARY PRELIMINARY PRELIMINARY
  826.  
  827.                    DEEMU
  828.            USER MODIFIABLE EXECUTABLE EMBEDDED DATA
  829.  
  830.                 Matthew Dillon            (SNAIL)
  831.                 891 Regal Rd.
  832.                   Berkeley, Ca. 94708
  833.                      USA
  834.  
  835.                 dillon@ucbvax.Berkeley.EDU        (APRANET)
  836.                 ...!ihnp4!ucbvax!dillon        (USENET)
  837.  
  838.  
  839.                  30 July 1988
  840.  
  841.     Includes:
  842.     CONFIG        -V1.00 of my config program
  843.     CLOCK        -V1.00 of my really-small non-intrusive clock program
  844.              (which uses DEEMU for window placement)
  845.     DEEMU.DOC   -Docs on DEEMU
  846.     SCRIPT.TXT  -Example script of configuring the clock executable
  847.     MAKEFILE
  848.     CONFIG.C
  849.     CLOCK.C
  850.  
  851.  
  852.     This document describes DEEMU, which allows end users to modify various
  853. parameters of a program by directly modifying the executable in question
  854. through standard programs.  This is what happens:
  855.  
  856.     (1) The programmer embedds a DEEMU structure at the very beginning
  857.     of his initialized data hunk.  Since the C startup module usually
  858.     contains only BSS declarations, a simple C declaration at the
  859.     beginning of your first module will suffice.
  860.  
  861.         ** THIS HAS BEEN TESTED WITH AZTEC C.  COULD SOMEBODY PLEASE
  862.            TEST IT WITH LATTICE?
  863.  
  864.  
  865.     (2) The user comes along and can modify various DEEMU entries in the
  866.     executable to customize the program to his needs.
  867.  
  868.     Thus, the programmer need not put any extra code into his program to
  869.     allow the user to modify parameters from the program.  Additionaly,
  870.     the script or initialization files that would otherwise have been
  871.     required are now nonexistant, making the user's enviroment that much
  872.     more streamlined and clean.
  873.  
  874.                 STRUCTURE FORMAT
  875.  
  876.     The programm should put the following declaration at the beginning of
  877.     his first C (or assembly, or whatever) module:
  878.  
  879.     long Deemu[] = {
  880.     'STRT', 0,
  881.     (other DEEMU entries)
  882.     'END ', 0
  883.     };
  884.  
  885.     Note that the name of the array is arbitrary.  This is an array of
  886.     longwords consisting of a START entry, intermediate entries, and an
  887.     END entry.    The format of each entry is:
  888.  
  889.     long type;        -longword describing the structure type
  890.     uword flags;        -RESERVED, SET TO 0
  891.     uword bytes;        -# of bytes
  892.     char data[bytes] + PAD0 -The structure data, padded to a WORD BOUNDRY
  893.  
  894.     The CONFIG program (yours, mine, anybody's) will check for 'STRT', 0 at
  895.     the beginning of every DATA HUNK in the program until it finds one,
  896.     then verifies the entire structure all the way to the 'END ', 0 is
  897.     correct, then prompts the user with the various structures allowing him
  898.     to modify them.
  899.  
  900.     The user gets very nice descriptive prompts for structure types that
  901.     CONFIG knows about.  The user can still modify structures CONFIG does
  902.     not know about, but will not get the descriptive prompts.
  903.  
  904.     ALL STRUCTURES ARE WORD ALIGNED.  That is, if a structure is not word
  905.     aligned it should be padded with a 0 at the end to make it so.  Thus,
  906.     EVEN WHEN THE #BYTES IS NOT WORD SIZED, the #bytes is extended to a
  907.     longword boundry to find the next DEEMU entry: bytes = (bytes+1)&~1
  908.  
  909.     Fields within the structure need not be word aligned.  This allows you
  910.     to embed standard Amiga structures.
  911.  
  912.  
  913.                 STANDARD STRUCTURES
  914.  
  915.     Since this is the first release, only a couple custom structures have
  916.     been defined so far.
  917.  
  918.     NOTE #1:    The entire structure need not be entered.  It is perfectly
  919.         acceptable to cut out the tail ends of structures that you
  920.         do not want to bother with.  For instance, you might have
  921.         the following for a NewWindow structure:
  922.  
  923.         'NW  ', 10, (short leftedge, topedge, width, height,
  924.                  ubyte detpen, blockpen)
  925.  
  926.                     OR
  927.  
  928.         'NW  ',  9, (short leftedge, topedge, width, height,
  929.                  ubyte detpen)
  930.             + one byte padding.
  931.  
  932.         In this case, the CONFIG program only prompts for those
  933.         fields that exist.
  934.  
  935.     NOTE #2:    Structures may be longer than the 'standard' size.  For
  936.         future compatibility.  The DEEMU program will prompt for
  937.         these fields but will not be able to give descriptions of
  938.         them to the user.
  939.  
  940.     STRT {    The START structure, must be the first DEEMU structure.
  941.     long type = 'STRT';
  942.     word flags= 0;
  943.     word size = 0;
  944.     };
  945.  
  946.     END  {    The END structure, must be the last DEEMU structure.
  947.     long type = 'END ';
  948.     word flags= 0;
  949.     word size = 0;
  950.     };
  951.  
  952.     TEXT {
  953.     long type = 'TEXT';
  954.     word flags= 0;
  955.     word size = N
  956.     char prompt[A];     N = A + B.    This includes the \0 after each string
  957.     char contents[B];
  958.     };
  959.  
  960.  
  961.     The contents string need not be exactly B long, but may terminate
  962.     with a \0 before it reaches the maximum allowed length.  In this
  963.     case the extra bytes at the end may be garbage.
  964.  
  965.     The contents string is thus limited to N-strlen(A)-2 character bytes,
  966.     not including the \0.
  967.  
  968.     THE PROMPT STRING MAY NOT BE MODIFIED BY THE USER.  SEE CLOCK.C FOR
  969.     EXAMPLE USAGE OF 'TEXT'.
  970.  
  971.     NOP {
  972.     long type = 'NOP ';
  973.     word flags = 0;
  974.     word size = N;
  975.     };
  976.  
  977.     No operation.  The data, if any, can be modified, but will probably
  978.     not be used by the program.
  979.  
  980.     DATA {
  981.     long type = 'DATA';
  982.     word flags = 0;
  983.     word size = N;
  984.     };
  985.  
  986.     Program dependant data.  Contents and ordering are defined by the
  987.     program.  The documentation for the program will tell you which
  988.     word means what (the CONFIG program prompts for the data in WORD
  989.     sized chunks).
  990.  
  991.     TRCT {
  992.     long type = 'TRCT';
  993.     word flags = 0;
  994.     word size = N;
  995.     short pri;
  996.     short cpu;
  997.     long chipmem;
  998.     long generalmem;
  999.     };
  1000.  
  1001.     Task/Resource Control.    Dynamic specification of the task priority.
  1002.     pri:
  1003.  
  1004.         Specify the task priority.    If bit 8 ($100) is set, an absolute
  1005.         priority is given in the low byte.    If bit 8 is clear, a
  1006.         priority relative to the startup-priority is given. (i.e. a
  1007.         1 means, 1 over my priority when I started up).
  1008.  
  1009.     cpu:    0-FFFF
  1010.  
  1011.         Specify how much of a CPU hog this program can be, in
  1012.         percentage (FFFF=100%).  Most programs ignore the field.
  1013.  
  1014.     chipmem/generalmem:
  1015.  
  1016.         some value representing the maximum #bytes of memory you want
  1017.         this program to use.  These fields do not apply to most
  1018.         programs but could come in useful in, say, a disk cache program
  1019.         or something like that.
  1020.  
  1021.         NOTE that there is no specification for 'fast' memory. chipmem
  1022.         refers to specific CHIP allocations the program makes, and
  1023.         generalmem refers to non-specific allocations the program might
  1024.         make.
  1025.  
  1026.  
  1027.     NW {
  1028.     long type = 'NW  ';
  1029.     word flags= 0;
  1030.     word size = N;        (usually 8 or 10 bytes.. partial NewWindow structure)
  1031.     (A partial NewWindow structure)
  1032.     };
  1033.  
  1034.     struct NewWindow NW;
  1035.     'NW  ', (0-sizeof(NewWindow))L, <data>
  1036.  
  1037.     The NewWindow structure.  However, the contents of LeftEdge,
  1038.     TopEdge, Width, and Height, are allowed to be NEGATIVE.
  1039.  
  1040.     TopEdge  < 0        : specify right edge relative to screen right
  1041.     LeftEdge < 0        : specify bottom edge relative to screen bottom
  1042.     Width    <= 0        : specify width relative to screen Width
  1043.     Height    <= 0        : specify height relative to screen height
  1044.  
  1045.     The programmer should do a sanity check of parameters after
  1046.     adjusting them properly.  The GetScreenData() should be used to
  1047.     retrieve screen information.
  1048.  
  1049.     For instance, specifying -1, -1 places the window as follows:
  1050.  
  1051.     ActualLeftEdge = Screen.Width - Nw.Width - 1;
  1052.     ActualTopEdge  = Screen.Height- Nw.Height- 1;
  1053.  
  1054.     SPECIFYING 0 FOR THE Nw.Width and/or Nw.Height should cause the
  1055.     window to be openned to its fullest size in that dimension.
  1056.  
  1057.     IF YOU USE THE 'NW  ' DEEMU STRUCTURE, YOU MUST BE ABLE TO HANDLE
  1058.     THESE SPECIAL CONDITION!
  1059.  
  1060.  
  1061.                 EXAMPLE
  1062.  
  1063. short Deemu[] = {
  1064.     'ST','RT', 0, 0,
  1065.     'NW','  ', 0, 9, -16, -8, 64, 32, -1, 0,
  1066.     'TE','XT', 0, 16, 'HI', '\0T', 'ES', 'T.', 0, 0, 0, 0,
  1067.     'EN','ND', 0, 0
  1068. };
  1069.  
  1070.  
  1071.     We have a STRT structure of 0 length (it MUST be 0 length).
  1072.  
  1073.     We then have the first 9 bytes of a NewWindow structure:
  1074.     short LeftEdge = -16;
  1075.     short TopEdge  = -8;
  1076.     short Width    = 64;
  1077.     short Height   = 32;
  1078.     char  DetailPen= -1;
  1079.  
  1080.     NOTE: The NW structure is padded to a word boundry with a 0, this
  1081.     0 is *NOT*, I repeat *NOT* the char BlockPen; specification, which
  1082.     normally comes after DetailPen.
  1083.  
  1084.     And, before the END we have a 'TEXT' entry with the prompt "HI" and
  1085.     the contents "TEST".  The user is allowed to modify the contents and
  1086.     up to 12 characters (not including the \0) may be used.  For TEXT, no
  1087.     more than 128 bytes total should be allocated.
  1088.  
  1089.                   LIMITATIONS
  1090.  
  1091.     Currently the config program only checks the first 32 longwords of
  1092.     each DATA hunk.  This is done mainly to prevent the possibility that
  1093.     non DEEMU data might look like a DEEMU header, but also taking into
  1094.     account that the linker might put some amount of data in the hunk
  1095.     before it gets to the DEEMU data.
  1096.  
  1097.     The Aztec linker (don't know about the others) sticks stuff before
  1098.     your own (jump tables when using the small code model).  If your
  1099.     program is big enough, the DEEMU data might be out of reach.  The
  1100.     solution is to place the DEEMU data in its own hunk, which can be
  1101.     accomplished with a little more work and various linker options.
  1102.  
  1103.     Future CONFIG programs will fix the problem.
  1104.  
  1105. \Rogue\Monster\
  1106. else
  1107.   echo "will not over write config.doc"
  1108. fi
  1109. if [ `wc -c config.doc | awk '{printf $1}'` -ne 9048 ]
  1110. then
  1111. echo `wc -c config.doc | awk '{print "Got " $1 ", Expected " 9048}'`
  1112. fi
  1113. if `test ! -s deemu.doc`
  1114. then
  1115. echo "writing deemu.doc"
  1116. cat > deemu.doc << '\Rogue\Monster\'
  1117.  
  1118.     PRELIMINARY PRELIMINARY PRELIMINARY PRELIMINARY PRELIMINARY PRELIMINARY
  1119.  
  1120.                    DEEMU
  1121.            USER MODIFIABLE EXECUTABLE EMBEDDED DATA
  1122.  
  1123.                 Matthew Dillon            (SNAIL)
  1124.                 891 Regal Rd.
  1125.                   Berkeley, Ca. 94708
  1126.                      USA
  1127.  
  1128.                 dillon@ucbvax.Berkeley.EDU        (APRANET)
  1129.                 ...!ihnp4!ucbvax!dillon        (USENET)
  1130.  
  1131.  
  1132.                  30 July 1988
  1133.  
  1134.     Includes:
  1135.     CONFIG        -V1.00 of my config program
  1136.     CLOCK        -V1.00 of my really-small non-intrusive clock program
  1137.              (which uses DEEMU for window placement)
  1138.     DEEMU.DOC   -Docs on DEEMU
  1139.     SCRIPT.TXT  -Example script of configuring the clock executable
  1140.     MAKEFILE
  1141.     CONFIG.C
  1142.     CLOCK.C
  1143.  
  1144.  
  1145.     This document describes DEEMU, which allows end users to modify various
  1146. parameters of a program by directly modifying the executable in question
  1147. through standard programs.  This is what happens:
  1148.  
  1149.     (1) The programmer embedds a DEEMU structure at the very beginning
  1150.     of his initialized data hunk.  Since the C startup module usually
  1151.     contains only BSS declarations, a simple C declaration at the
  1152.     beginning of your first module will suffice.
  1153.  
  1154.         ** THIS HAS BEEN TESTED WITH AZTEC C.  COULD SOMEBODY PLEASE
  1155.            TEST IT WITH LATTICE?
  1156.  
  1157.  
  1158.     (2) The user comes along and can modify various DEEMU entries in the
  1159.     executable to customize the program to his needs.
  1160.  
  1161.     Thus, the programmer need not put any extra code into his program to
  1162.     allow the user to modify parameters from the program.  Additionaly,
  1163.     the script or initialization files that would otherwise have been
  1164.     required are now nonexistant, making the user's enviroment that much
  1165.     more streamlined and clean.
  1166.  
  1167.                 STRUCTURE FORMAT
  1168.  
  1169.     The programm should put the following declaration at the beginning of
  1170.     his first C (or assembly, or whatever) module:
  1171.  
  1172.     long Deemu[] = {
  1173.     'STRT', 0,
  1174.     (other DEEMU entries)
  1175.     'END ', 0
  1176.     };
  1177.  
  1178.     Note that the name of the array is arbitrary.  This is an array of
  1179.     longwords consisting of a START entry, intermediate entries, and an
  1180.     END entry.    The format of each entry is:
  1181.  
  1182.     long type;        -longword describing the structure type
  1183.     uword flags;        -RESERVED, SET TO 0
  1184.     uword bytes;        -# of bytes
  1185.     char data[bytes] + PAD0 -The structure data, padded to a WORD BOUNDRY
  1186.  
  1187.     The CONFIG program (yours, mine, anybody's) will check for 'STRT', 0 at
  1188.     the beginning of every DATA HUNK in the program until it finds one,
  1189.     then verifies the entire structure all the way to the 'END ', 0 is
  1190.     correct, then prompts the user with the various structures allowing him
  1191.     to modify them.
  1192.  
  1193.     The user gets very nice descriptive prompts for structure types that
  1194.     CONFIG knows about.  The user can still modify structures CONFIG does
  1195.     not know about, but will not get the descriptive prompts.
  1196.  
  1197.     ALL STRUCTURES ARE WORD ALIGNED.  That is, if a structure is not word
  1198.     aligned it should be padded with a 0 at the end to make it so.  Thus,
  1199.     EVEN WHEN THE #BYTES IS NOT WORD SIZED, the #bytes is extended to a
  1200.     longword boundry to find the next DEEMU entry: bytes = (bytes+1)&~1
  1201.  
  1202.     Fields within the structure need not be word aligned.  This allows you
  1203.     to embed standard Amiga structures.
  1204.  
  1205.  
  1206.                 STANDARD STRUCTURES
  1207.  
  1208.     Since this is the first release, only a couple custom structures have
  1209.     been defined so far.
  1210.  
  1211.     NOTE #1:    The entire structure need not be entered.  It is perfectly
  1212.         acceptable to cut out the tail ends of structures that you
  1213.         do not want to bother with.  For instance, you might have
  1214.         the following for a NewWindow structure:
  1215.  
  1216.         'NW  ', 10, (short leftedge, topedge, width, height,
  1217.                  ubyte detpen, blockpen)
  1218.  
  1219.                     OR
  1220.  
  1221.         'NW  ',  9, (short leftedge, topedge, width, height,
  1222.                  ubyte detpen)
  1223.             + one byte padding.
  1224.  
  1225.         In this case, the CONFIG program only prompts for those
  1226.         fields that exist.
  1227.  
  1228.     NOTE #2:    Structures may be longer than the 'standard' size.  For
  1229.         future compatibility.  The DEEMU program will prompt for
  1230.         these fields but will not be able to give descriptions of
  1231.         them to the user.
  1232.  
  1233.     STRT {    The START structure, must be the first DEEMU structure.
  1234.     long type = 'STRT';
  1235.     word flags= 0;
  1236.     word size = 0;
  1237.     };
  1238.  
  1239.     END  {    The END structure, must be the last DEEMU structure.
  1240.     long type = 'END ';
  1241.     word flags= 0;
  1242.     word size = 0;
  1243.     };
  1244.  
  1245.     TEXT {
  1246.     long type = 'TEXT';
  1247.     word flags= 0;
  1248.     word size = N
  1249.     char prompt[A];     N = A + B.    This includes the \0 after each string
  1250.     char contents[B];
  1251.     };
  1252.  
  1253.  
  1254.     The contents string need not be exactly B long, but may terminate
  1255.     with a \0 before it reaches the maximum allowed length.  In this
  1256.     case the extra bytes at the end may be garbage.
  1257.  
  1258.     The contents string is thus limited to N-strlen(A)-2 character bytes,
  1259.     not including the \0.
  1260.  
  1261.     THE PROMPT STRING MAY NOT BE MODIFIED BY THE USER.  SEE CLOCK.C FOR
  1262.     EXAMPLE USAGE OF 'TEXT'.
  1263.  
  1264.     NOP {
  1265.     long type = 'NOP ';
  1266.     word flags = 0;
  1267.     word size = N;
  1268.     };
  1269.  
  1270.     No operation.  The data, if any, can be modified, but will probably
  1271.     not be used by the program.
  1272.  
  1273.     DATA {
  1274.     long type = 'DATA';
  1275.     word flags = 0;
  1276.     word size = N;
  1277.     };
  1278.  
  1279.     Program dependant data.  Contents and ordering are defined by the
  1280.     program.  The documentation for the program will tell you which
  1281.     word means what (the CONFIG program prompts for the data in WORD
  1282.     sized chunks).
  1283.  
  1284.     TRCT {
  1285.     long type = 'TRCT';
  1286.     word flags = 0;
  1287.     word size = N;
  1288.     short pri;
  1289.     short cpu;
  1290.     long chipmem;
  1291.     long generalmem;
  1292.     };
  1293.  
  1294.     Task/Resource Control.    Dynamic specification of the task priority.
  1295.     pri:
  1296.  
  1297.         Specify the task priority.    If bit 8 ($100) is set, an absolute
  1298.         priority is given in the low byte.    If bit 8 is clear, a
  1299.         priority relative to the startup-priority is given. (i.e. a
  1300.         1 means, 1 over my priority when I started up).
  1301.  
  1302.     cpu:    0-FFFF
  1303.  
  1304.         Specify how much of a CPU hog this program can be, in
  1305.         percentage (FFFF=100%).  Most programs ignore the field.
  1306.  
  1307.     chipmem/generalmem:
  1308.  
  1309.         some value representing the maximum #bytes of memory you want
  1310.         this program to use.  These fields do not apply to most
  1311.         programs but could come in useful in, say, a disk cache program
  1312.         or something like that.
  1313.  
  1314.         NOTE that there is no specification for 'fast' memory. chipmem
  1315.         refers to specific CHIP allocations the program makes, and
  1316.         generalmem refers to non-specific allocations the program might
  1317.         make.
  1318.  
  1319.  
  1320.     NW {
  1321.     long type = 'NW  ';
  1322.     word flags= 0;
  1323.     word size = N;        (usually 8 or 10 bytes.. partial NewWindow structure)
  1324.     (A partial NewWindow structure)
  1325.     };
  1326.  
  1327.     struct NewWindow NW;
  1328.     'NW  ', (0-sizeof(NewWindow))L, <data>
  1329.  
  1330.     The NewWindow structure.  However, the contents of LeftEdge,
  1331.     TopEdge, Width, and Height, are allowed to be NEGATIVE.
  1332.  
  1333.     TopEdge  < 0        : specify right edge relative to screen right
  1334.     LeftEdge < 0        : specify bottom edge relative to screen bottom
  1335.     Width    <= 0        : specify width relative to screen Width
  1336.     Height    <= 0        : specify height relative to screen height
  1337.  
  1338.     The programmer should do a sanity check of parameters after
  1339.     adjusting them properly.  The GetScreenData() should be used to
  1340.     retrieve screen information.
  1341.  
  1342.     For instance, specifying -1, -1 places the window as follows:
  1343.  
  1344.     ActualLeftEdge = Screen.Width - Nw.Width - 1;
  1345.     ActualTopEdge  = Screen.Height- Nw.Height- 1;
  1346.  
  1347.     SPECIFYING 0 FOR THE Nw.Width and/or Nw.Height should cause the
  1348.     window to be openned to its fullest size in that dimension.
  1349.  
  1350.     IF YOU USE THE 'NW  ' DEEMU STRUCTURE, YOU MUST BE ABLE TO HANDLE
  1351.     THESE SPECIAL CONDITION!
  1352.  
  1353.  
  1354.                 EXAMPLE
  1355.  
  1356. short Deemu[] = {
  1357.     'ST','RT', 0, 0,
  1358.     'NW','  ', 0, 9, -16, -8, 64, 32, -1, 0,
  1359.     'TE','XT', 0, 16, 'HI', '\0T', 'ES', 'T.', 0, 0, 0, 0,
  1360.     'EN','ND', 0, 0
  1361. };
  1362.  
  1363.  
  1364.     We have a STRT structure of 0 length (it MUST be 0 length).
  1365.  
  1366.     We then have the first 9 bytes of a NewWindow structure:
  1367.     short LeftEdge = -16;
  1368.     short TopEdge  = -8;
  1369.     short Width    = 64;
  1370.     short Height   = 32;
  1371.     char  DetailPen= -1;
  1372.  
  1373.     NOTE: The NW structure is padded to a word boundry with a 0, this
  1374.     0 is *NOT*, I repeat *NOT* the char BlockPen; specification, which
  1375.     normally comes after DetailPen.
  1376.  
  1377.     And, before the END we have a 'TEXT' entry with the prompt "HI" and
  1378.     the contents "TEST".  The user is allowed to modify the contents and
  1379.     up to 12 characters (not including the \0) may be used.  For TEXT, no
  1380.     more than 128 bytes total should be allocated.
  1381.  
  1382.                   LIMITATIONS
  1383.  
  1384.     Currently the config program only checks the first 32 longwords of
  1385.     each DATA hunk.  This is done mainly to prevent the possibility that
  1386.     non DEEMU data might look like a DEEMU header, but also taking into
  1387.     account that the linker might put some amount of data in the hunk
  1388.     before it gets to the DEEMU data.
  1389.  
  1390.     The Aztec linker (don't know about the others) sticks stuff before
  1391.     your own (jump tables when using the small code model).  If your
  1392.     program is big enough, the DEEMU data might be out of reach.  The
  1393.     solution is to place the DEEMU data in its own hunk, which can be
  1394.     accomplished with a little more work and various linker options.
  1395.  
  1396.     Future CONFIG programs will fix the problem.
  1397.  
  1398. \Rogue\Monster\
  1399. else
  1400.   echo "will not over write deemu.doc"
  1401. fi
  1402. if [ `wc -c deemu.doc | awk '{printf $1}'` -ne 9048 ]
  1403. then
  1404. echo `wc -c deemu.doc | awk '{print "Got " $1 ", Expected " 9048}'`
  1405. fi
  1406. if `test ! -s script.txt`
  1407. then
  1408. echo "writing script.txt"
  1409. cat > script.txt << '\Rogue\Monster\'
  1410.  
  1411.  
  1412.         Example session with Config, configuring CLOCK.
  1413.  
  1414.         Please refer to CLOCK.C to see how the DEEMU structure
  1415.         is embedded and how the clock program handles the data.
  1416.  
  1417.     This particular script file shows placing the analog clock as a
  1418.     32x16 window in the upper right hand corner of the screen.
  1419.  
  1420.                     -Matt
  1421.  
  1422.  
  1423. 1> config clock
  1424. CONFIG V1.00, Matthew Dillon
  1425. 2 entries found
  1426.  
  1427. ----(NW  , 8): NEW WINDOW STRUCTURE
  1428.  note: (Negative = Relative to Screen Right)
  1429.        LeftEdge (    $0000      0) : -1
  1430.  note: (Negative = Relative to Screen Bottom)
  1431.        TopEdge    (    $0000      0) : 10
  1432.  note: (0 = Full Width, < 0 = ScreenWidth - (-width)
  1433.        Width    (    $0020     32) :
  1434.  note: (0 = Full Height,< 0 = ScreenHeight- (-height)
  1435.        Height    (    $0010     16) :
  1436.  
  1437. ----(TEXT,16): TEXT
  1438. HI        (12 chars max) (          TEST.) : IWasHere
  1439.  
  1440. Write data back to file (y/n): y
  1441. File updated
  1442. 1>
  1443.  
  1444.  
  1445. \Rogue\Monster\
  1446. else
  1447.   echo "will not over write script.txt"
  1448. fi
  1449. if [ `wc -c script.txt | awk '{printf $1}'` -ne 891 ]
  1450. then
  1451. echo `wc -c script.txt | awk '{print "Got " $1 ", Expected " 891}'`
  1452. fi
  1453. echo "Finished archive 1 of 1"
  1454. # if you want to concatenate archives, remove anything after this line
  1455. exit
  1456. -- 
  1457. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  1458. Have five nice days.
  1459.